package it.uniroma2.exp.dtk;

import it.uniroma2.exp.AbstractExperiment;
import it.uniroma2.exp.tools.AvgVarCalculator;
import it.uniroma2.util.math.ArrayMath;
import it.uniroma2.util.vector.RandomVectorGenerator;
import it.uniroma2.util.vector.VectorComposer;

/**
 * @author Lorenzo Dell'Arciprete
 * 
 * This experiment computes the dot product between 2 sums of N random vectors, where M of them are in common
 *
 */
public class VectorTester extends AbstractExperiment {
	
	public static final int[] NUMBER_OF_VECTORS = {20, 50, 100, 200, 500};
	public static final int[] NUMBER_OF_COMMON_VECTORS = {0, 1, 2, 5, 10}; 
	public static final int TRIALS = 10;
	
	public static void main(String[] args) {
		VectorTester vt = new VectorTester();
		vt.setVectorSize(4096);
		vt.runAll();
	}

	@Override
	protected void runExperiment() throws Exception {
		VectorComposer vc = new VectorComposer();
		RandomVectorGenerator rvg = new RandomVectorGenerator(vectorSize, randomOffset);
		out.print("\t");
		for (int commonVecs : NUMBER_OF_COMMON_VECTORS)
			out.print(commonVecs+"\t\t");
		for (int numVecs : NUMBER_OF_VECTORS) {
			rvg.setRandomSeed(vectorSize*numVecs);
			out.print("\n"+numVecs+"\t");
			for (int commonVecs : NUMBER_OF_COMMON_VECTORS) {
				AvgVarCalculator avg = new AvgVarCalculator();
				for (int k = 0; k < TRIALS; k++) {
					double[] sum1 = rvg.generateZeroVector();
					double[] sum2 = rvg.generateZeroVector();
					for (int i = 0; i < commonVecs; i++) {
						double[] vec = rvg.generateRandomVector();
						sum1 = vc.sum(sum1, vec);
						sum2 = vc.sum(sum2, vec);
					}
					for (int i = 0; i < numVecs - commonVecs; i++)
						sum1 = vc.sum(sum1, rvg.generateRandomVector());
					for (int i = 0; i < numVecs - commonVecs; i++)
						sum2 = vc.sum(sum2, rvg.generateRandomVector());
					avg.addSample(ArrayMath.dot(sum1, sum2));
				}
				out.print(avg.getFormattedResult()+"\t");
			}
		}
	}

}
